#include "LSIcompute.h"

LSIcompute::LSIcompute(double * TFM, const int d, const int t, double * approxiError, int * pGroups, int * pPseudoTermNum) : docNum(d), termNum(t)
{	
	/*int iter = 0;
	this->pTFM = new double [docNum * termNum];
	for(int i = 0; i < docNum; i++)
	for(int j = 0; j < termNum; j++)
	pTFM[iter ++] = TFM[i][j];*/

	this->pTFM = TFM;
	this->approxiErrorMax = approxiError;
	this->groups = pGroups;
	this->psTermNum = pPseudoTermNum;
	//*(this->psTermNum) = 2;
}

LSIcompute::~LSIcompute()
{
	delete [] this->pTFM;
	for(int i = 0; i < docNum; i++)
		delete [] pseudoTM[i];
	delete [] pseudoTM;
}

void LSIcompute::ComputeSVD()
{	
	std::cout << "Computing SVD start..." << std::endl;

	A.setcontent(this->docNum, this->termNum, this->pTFM);

	alglib::rmatrixsvd(A, this->docNum, this->termNum, 1, 1, 0, S, U, Vt);

	std::cout << "Computing SVD finished." << std::endl;
}

void LSIcompute::runCompution()
{
	this->ComputeSVD();

	this->ComputeApproxiError();

	this->InitializePseudoTM();

	this->MatchToGroup();

	/*double result = w[0];
	double result2 = w[1];
	double result3 = u[0][0];
	double result4 = u[0][1];
	double result5 = u[1][0];
	double result6 = u[1][1];
	double result7 = vt[0][0];
	double result8 = vt[0][1];
	double result9 = vt[1][0];
	double result10 = vt[1][1];

	double result11 = u[2][0];
	double result12 = u[2][1];
	double result13 = u[4][0];
	double result14 = u[4][1];*/
}

//void LSIcompute::ComputeApproxiError()
//{
//	double nominator = 0;
//	double denominator = 0;
//	double dError = 0;
//
//	if (this->termNum <= *psTermNum)	return;
//
//	bool flag = true;
//
//	do{
//		nominator = 0;
//		denominator = 0;
//
//		if(*psTermNum < S.length())
//		{
//			for(int i = 0; i < S.length(); i++){
//				if (i < (*psTermNum))	nominator += (S[i] * S[i]);
//				denominator += (S[i] * S[i]);
//			}
//			dError = 1.0 - ( (nominator ) / denominator);
//			if( dError > *(this->approxiErrorMax)) 
//			{
//				flag = false;
//				*(this->approxiErrorMax) = dError;
//				if( (*psTermNum) > 2) (*psTermNum) --;
//			}
//			else
//				(*psTermNum) ++;
//		}
//		else
//		{
//			flag = false;
//			*psTermNum =  S.length();
//		}
//	}
//	while(flag);
//}

void LSIcompute::ComputeApproxiError()
{
	double nominator = 0;
	double denominator = 0;
	double dError = 0;

	if (this->termNum <= *psTermNum)	return;

	bool flag = true;

	for(int i = 0; i < S.length(); i++){
		if (i < (*psTermNum))	nominator += (S[i] * S[i]);
		denominator += (S[i] * S[i]);
	}
	dError = 1.0 - ( (nominator ) / denominator);

	*(this->approxiErrorMax) = dError;
}

void LSIcompute::InitializePseudoTM()
{
	std::cout << "InitializePseudoTM() start..." << std::endl;
	this->pseudoTM = new double * [this->docNum];
	for(int i = 0; i < docNum; i++)
	{
		this->pseudoTM[i] = new double [*psTermNum];
		for(int j = 0; j < *psTermNum; j++)
		{
			this->pseudoTM[i][j] = ( U[i][j] * S[j] );
		}
	}
	std::cout << "InitializePseudoTM() finished." << std::endl;
}

void LSIcompute::MatchToGroup()
{
	std::cout << "MatchToGroup() start..." << std::endl;

	int maxIndex = 0;
	double maxVal;

	for(int i = 0; i < docNum; i++)
	{
		maxVal = this->pseudoTM[i][0];
		maxIndex = 0;
		for(int j = 1; j < *psTermNum; j++)
		{
			if(maxVal < this->pseudoTM[i][j])
			{
				maxVal = this->pseudoTM[i][j];
				maxIndex = j;
			}
		}

		this->groups[i] = maxIndex + 1;
	}
	std::cout << "MatchToGroup() finished." << std::endl;
}